package sculove.spring.framework.util;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.sql.Clob;


/**
 * Oracle에서 CLOB 사용시 사용한다.
 * @author 손찬욱
 * @version 1.0
 * @since 2008.12.31
 *
 *<p>
 * 일반적으로 Clob형태의 필드는 일반 sql문과 같이 처리할수 없습니다.
 * 따라서 Clob 필드만 따로 얻고, 기본적인 sql문 데이터를 따로 
 * 처리하는 방향으로 개발을 하셔야 합니다.
 *
 * [추가 모듈]
 * 1. void ClobUtil.writeClob(Clob clob, String source);  => source 내용을 clob에 넣는다.
 * 2. String ClobUtil.readClob(Clob clob);  => clob내용을 읽어 String으로 반환한다.
 * 
 * [사용법]
 * 1. update시
 *   예)
 *   // 1. update할 Clob 데이터를 첫번째 필드에서 추출한다. 이때 for update를 이용하여 해당 값을 update 한다.
 *   String sourceStr = "입력할값";
 *   pstmt = getConnection().prepareStatement("select email_cnts from TB_BZZZEMS_RLTM_EMAIL_SND for update");
 *   ResultSet rs=pstmt.executeQuery();
 *   while(rs.next())
 *      ClobUtil.writeClob(rs.getClob(1), sourceStr);
 * 
 *   // 2. Clob를 제외한 다른 데이터를 insert/update한다.
 *    .....
 * 
 * 2. read시
 *   예)
 * 
 *   // 1. read할 Clob 데이터를 첫번째 필드에서 추출한다.
 *   String targetStr = null;
 *   pstmt = getConnection().prepareStatement("select email_cnts from TB_BZZZEMS_RLTM_EMAIL_SND");
 *   ResultSet rs=pstmt.executeQuery();
 *   while(rs.next())
 *       targetStr = ClobUtil.readClob(rs.getClob(1)));
 * 
 *   // 2. Clob를 제외한 다른 데이터를 조회한다.
 *    .....
 * 
 *  3. insert 시에는 Clob 부분을 empty_clob()이라는 오라클 함수로 초기값을 만든 후, update시킨다. 
 *</p>
 */
public class ClobUtil {
    public static String readClob(Clob clob) throws Exception
    {
    	return readClob(clob, 4096);
    }
    
    /**
     *  clob형태를  읽는 Method
     * @param clob
     * @return
     * @throws Exception
     */    
	public static String readClob(Clob clob, int bufferSize) throws Exception
	{
		StringBuffer outputBuffer = new StringBuffer();
		Reader reader = null;
		char[] inputBuffer=new char[bufferSize];
		int len = 0;
		
		try {
			reader = clob.getCharacterStream();
			while( (len = reader.read(inputBuffer)) != -1)
				outputBuffer.append(inputBuffer, 0 , len);
			return outputBuffer.toString();
		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			try { if(reader != null) reader.close(); } catch (IOException e) {}
		}
	}
	
	public static void writeClob(Clob clob, String data) throws Exception
	{
		writeClob(clob,data,1024);
	}
	
	/**
	 * clob형태를  쓰는 Method
	 * clob형태에서 autocommit이 false일때 가능하다.
	 * @param clob
	 * @param data
	 * @param bufferSize
	 * @throws Exception
	 */
	public static void writeClob(Clob clob, String data, int bufferSize) throws Exception
	{
		Reader reader = new CharArrayReader(data.toCharArray());
		Writer writer = null;
		char[] inputBuffer=new char[bufferSize];
		int len = 0;
		
		try {
			clob.truncate(0);
			writer = clob.setCharacterStream(0);
			while( (len = reader.read(inputBuffer)) != -1 ) {
				writer.write(inputBuffer, 0 , len);
				inputBuffer=new char[bufferSize];
			}
		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			try { if(writer != null) writer.close(); } catch (Exception e) {}
		}
	}
}